/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.explorer.view;
import java.awt.dnd.*;
import java.awt.Point;
import java.awt.datatransfer.*;
import javax.swing.JList;
import javax.swing.SwingUtilities;
import org.openide.nodes.Node;
import org.openide.nodes.NodeTransfer;
import org.openide.util.datatransfer.PasteType;
import org.openide.util.datatransfer.ExTransferable;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
/**
*
* @author Dafe Simonek
*/
final class ListViewDropSupport implements DropTargetListener,
Runnable {
// Attributes
/** true if support is active, false otherwise */
boolean active = false;
/** Drop target asociated with the tree */
DropTarget dropTarget;
/** The index of last item the cursor hotspot was above */
int lastIndex = -1;
// Associations
/** View manager. */
protected ListView view;
/** The component we are supporting with drop support */
protected JList list;
/** For managing visual appearance of JList cells. */
protected NodeRenderer.List cellRenderer;
// Operations
/** Creates new TreeViewDropSupport */
public ListViewDropSupport (ListView view, JList list) {
this.view = view;
this.list = list;
//cellRenderer = (NodeListCellRenderer)list.getCellRenderer();
}
/** User is starting to drag over us */
public void dragEnter (DropTargetDragEvent dtde) {
lastIndex = indexWithCheck(dtde);
if (lastIndex < 0)
dtde.rejectDrag();
else {
dtde.acceptDrag(dtde.getDropAction());
NodeRenderer.dragEnter(
list.getModel().getElementAt(lastIndex));
list.repaint(list.getCellBounds(lastIndex, lastIndex));
}
}
/** User drags over us */
public void dragOver (DropTargetDragEvent dtde) {
int index = indexWithCheck(dtde);
if (index < 0) {
dtde.rejectDrag();
if (lastIndex >= 0) {
NodeRenderer.dragExit();
list.repaint(list.getCellBounds(lastIndex, lastIndex));
lastIndex = -1;
}
} else {
dtde.acceptDrag(dtde.getDropAction());
if (lastIndex != index) {
if (lastIndex < 0)
lastIndex = index;
NodeRenderer.dragExit();
NodeRenderer.dragEnter(list.getModel().getElementAt(index));
list.repaint(list.getCellBounds(lastIndex, index));
lastIndex = index;
}
}
}
public void dropActionChanged (DropTargetDragEvent dtde) {
//System.out.println("Changing drop action..."); // NOI18N
// PENDING...?
}
/** User exits the dragging */
public void dragExit (DropTargetEvent dte) {
if (lastIndex >= 0) {
NodeRenderer.dragExit();
list.repaint(list.getCellBounds(lastIndex, lastIndex));
}
}
/** Performs the drop action, if we are dropping on
* right node and target node agrees.
*/
public void drop (DropTargetDropEvent dtde) {
//System.out.println("Dropping!!!"); // NOI18N
// obtain the node we have cursor on
int index = list.locationToIndex(dtde.getLocation());
Object obj = null;
// return if conditions are not satisfied
int dropAction = dtde.getDropAction();
if ((index < 0) ||
((dropAction & view.getAllowedDropActions()) == 0) ||
!((obj = list.getModel().getElementAt(index)) instanceof Node)) {
dtde.rejectDrop();
return;
}
// get paste types for given transferred transferable
PasteType[] pt =
DragDropUtilities.getPasteTypes((Node)obj, dtde.getTransferable());
if ((pt == null) || (pt.length <= 0)) {
dtde.dropComplete(false);
// something is wrong, notify user
// ugly hack, but if we don't wait, deadlock will come
// (sun's issue....)
RequestProcessor.postRequest(this, 500);
return;
}
// finally perform the drop
dtde.acceptDrop(dropAction);
if (dropAction == DnDConstants.ACTION_LINK) {
// show popup menu to the user
// PENDING
} else {
DragDropUtilities.performDrop(pt[0]);
}
}
/** Activates or deactivates Drag support on asociated JTree
* component
* @param active true if the support should be active, false
* otherwise
*/
public void activate (boolean active) {
if (this.active == active)
return;
this.active = active;
getDropTarget().setActive(active);
}
/** Implementation of the runnable interface.
* Notifies user in AWT thread. */
public void run () {
SwingUtilities.invokeLater(
new Runnable () {
public void run () {
DragDropUtilities.dropNotSuccesfull();
}
}
);
}
/** @return The tree path to the node the cursor is above now or
* null if no such node currently exists or if conditions were not
* satisfied to continue with DnD operation.
*/
int indexWithCheck (DropTargetDragEvent dtde) {
int dropAction = dtde.getDropAction();
// check actions
if ((dropAction & view.getAllowedDropActions()) == 0)
return -1;
// check location
int index = list.locationToIndex(dtde.getLocation());
Object obj = null;
if ((index < 0) ||
!((obj = list.getModel().getElementAt(index)) instanceof Node))
return -1;
/* JST: Is necessary? Cannot be replaced by the use of special
* transferable?
// accept only node data flavors or multi flavor
if (!dtde.isDataFlavorSupported(NodeTransfer.nodeCutFlavor) &&
!dtde.isDataFlavorSupported(NodeTransfer.nodeCopyFlavor) &&
!dtde.isDataFlavorSupported(ExTransferable.multiFlavor))
return -1;
*/
// succeeded
return index;
}
/** Safe accessor to the drop target which is asociated
* with the tree */
DropTarget getDropTarget () {
if (dropTarget == null) {
dropTarget =
new DropTarget(list, view.getAllowedDropActions(),
this, false);
}
return dropTarget;
}
/** Safe getter for the cell renderer of asociated list */
NodeRenderer.List getCellRenderer () {
if (cellRenderer == null)
cellRenderer = (NodeRenderer.List)list.getCellRenderer();
return cellRenderer;
}
}
/*
* Log
* 8 Gandalf 1.7 1/13/00 Ian Formanek NOI18N
* 7 Gandalf 1.6 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 6 Gandalf 1.5 8/27/99 Jaroslav Tulach New threading model &
* Children.
* 5 Gandalf 1.4 6/30/99 Jaroslav Tulach Drag and drop support
* 4 Gandalf 1.3 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 3 Gandalf 1.2 5/17/99 David Simonek comments removed
* 2 Gandalf 1.1 4/30/99 David Simonek
* 1 Gandalf 1.0 4/27/99 David Simonek
* $
*/